package com.geoai.featstatusbar.view

import android.os.Bundle
import android.util.Log
import com.geoai.basiclib.base.fragment.BaseVVDDialogFragment
import com.geoai.basiclib.engine.toast.toastSuccess
import com.geoai.basiclib.ext.gone
import com.geoai.basiclib.ext.visible
import com.geoai.featstatusbar.R
import com.geoai.featstatusbar.databinding.FragmentRtkSatelliteBinding
import com.geoai.featstatusbar.mvi.vm.RtkSatelliteViewModel
import com.geoai.mavlink.geoainet.rtk.component.CmccRtkManager
import com.geoai.mavlink.geoainet.rtk.component.NtripClientRtkManager
import com.geoai.mavlink.geoainet.rtk.component.QxRtkManager
import com.geoai.mavlink.geoainet.rtk.component.SixentsRtkManager
import com.geoai.mavlink.geoainet.rtk.component.account.CmccAccount
import com.geoai.mavlink.geoainet.rtk.component.account.NtripClientAccount
import com.geoai.mavlink.geoainet.rtk.component.account.QxAccount
import com.geoai.mavlink.geoainet.rtk.component.account.SixentsAccount
import com.geoai.mavlink.geoainet.rtk.enums.RtkComponentType
import com.geoai.uicore.custom.ui.GEOUISelectorDialog
import com.zkyt.lib_msdk_ext.component.RtkManagerExt
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo

/**
 * @Author      : Ronny
 * @Email       : Ronny_xie@hotmail.com
 * @Date        : on 2024-04-07 10:48.
 * @Description :
 */
class RtkSatelliteDialogFragment: BaseVVDDialogFragment<RtkSatelliteViewModel, FragmentRtkSatelliteBinding>() {

    override fun init(savedInstanceState: Bundle?) {
        initRtkModuleEnable()
        initRtkModuleSelector()
        initRtkParamsSaveAction()
        initRtkConnectionAction()
        updateRtkModuleType()

        RtkManagerExt.getRtkStateInfoObservable()
            .observeOn(AndroidSchedulers.mainThread())
            .map { it.get() }
            .subscribe {
                mBinding.tvRtkStatus.text = getNtripErrorCodeMessage(it.serviceCode.value())
                mBinding.tvPosType.text = getGpsPosTypeMessage(it.posType.value())
                mBinding.tvLocation.text = String.format("%.7f ; %.7f", it.latitude, it.longitude)

                mBinding.tvRtkGpsCount.text = it.baseStationInfo?.gpsSatelliteInfo?.satelliteNum?.count()?.toString()?:"0"
                mBinding.tvRtkBdsCount.text = it?.baseStationInfo?.bdsSatelliteInfo?.satelliteNum?.count()?.toString()?:"0"
                mBinding.tvRtkGalileoCount.text = it?.baseStationInfo?.galileoSatelliteInfo?.satelliteNum?.count()?.toString()?:"0"
                mBinding.tvRtkGlonassCount.text = it?.baseStationInfo?.glonassSatelliteInfo?.satelliteNum?.count()?.toString()?:"0"

                mBinding.tvBasestationHealthy.setContent("None")
                mBinding.tvBasestationLatitude.setContent(it.baseStationInfo?.baseStationLatitude?.toString()?:"0.0")
                mBinding.tvBasestationLongitude.setContent(it.baseStationInfo?.baseStationLongitude?.toString()?:"0.0")
                mBinding.tvBasestationAltitude.setContent(it.baseStationInfo?.baseStationAltitude?.toString()?:"0.0")
            }.addTo(mViewModel.compositeDisposable)
    }

    private fun initRtkConnectionAction() {
        mBinding.tvRtkConn.setOnClickListener {
            showStateLoading()
            RtkManagerExt.connectRx()
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    toastSuccess("success")
                    showStateSuccess()
                }) { error ->
                    showStateError(error.message)
                }.addTo(mViewModel.compositeDisposable)
        }
    }

    private fun initRtkParamsSaveAction() {
        mBinding.tvConfigConfirm.setOnClickListener {
            showStateLoading()
            RtkManagerExt.getOriginManager()?.let { rtkManager ->
                when (rtkManager.rtkComponentType) {
                    RtkComponentType.CUSTOM -> {
                        val ntripRtkManager: NtripClientRtkManager = (rtkManager.netWorkRtkManager as NtripClientRtkManager)
                        ntripRtkManager.setAccount(
                            NtripClientAccount(mBinding.ntripConfigRtkServer.param,
                            mBinding.ntripConfigRtkPort.param.toIntOrNull()?:0,
                            mBinding.ntripConfigRtkUsername.param,
                            mBinding.ntripConfigRtkPassword.param,
                            mBinding.ntripConfigRtkMount.param)
                        )
                    }
                    RtkComponentType.QX -> {
                        val qxRtkManager = (rtkManager.netWorkRtkManager as QxRtkManager)
                        qxRtkManager.setAccount(
                            QxAccount(
                            mBinding.qxConfigRtkId.param,
                            mBinding.qxConfigRtkType.param,
                            mBinding.qxConfigRtkAccount.param,
                            mBinding.qxConfigRtkSecret.param)
                        )
                    }
                    RtkComponentType.SIXENTS -> {
                        val sixentsRtkManager = (rtkManager.netWorkRtkManager as SixentsRtkManager)
                        sixentsRtkManager.setAccount(
                            SixentsAccount(
                            mBinding.sixentsConfigRtkId.param,
                            mBinding.sixentsConfigRtkType.param,
                            mBinding.sixentsConfigRtkAccount.param,
                            mBinding.sixentsConfigRtkSecret.param)
                        )
                    }
                    RtkComponentType.CMCC -> {
                        val cmccRtkManager = (rtkManager.netWorkRtkManager as CmccRtkManager)
                        cmccRtkManager.setAccount(CmccAccount(mBinding.cmccConfigRtkId.param))
                    }
                    else -> {rtkManager.disconnectRTK()}
                }
                showStateSuccess()
                toastSuccess("success")
            }
        }
    }

    private fun initRtkModuleSelector() {
        mBinding.tvRtkComponent.setOnClickListener {
            var currentSelectIndex = 0
            resources.getStringArray(R.array.fc_setting_rtk_model_selector).forEachIndexed { index, s ->
                if (s.equals(mBinding.tvRtkComponent.text)) {
                    currentSelectIndex = index + 1
                }
            }
            //展示RTK类型选择对话框
            GEOUISelectorDialog()
                .setTitle(resources.getString(R.string.fc_setting_rtk_selector_title))
                .setCurrentSelectIndex(currentSelectIndex)
                .setDataSource(resources.getStringArray(R.array.fc_setting_rtk_model_selector))
                .setConfirmButton { actionName, _ ->
                    val rtkType = when(actionName) {
                        getString(R.string.fc_setting_rtk_model_none) -> {RtkComponentType.NONE}
                        getString(R.string.fc_setting_rtk_model_qx) -> {RtkComponentType.QX}
                        getString(R.string.fc_setting_rtk_model_cmcc) -> {RtkComponentType.CMCC}
                        getString(R.string.fc_setting_rtk_model_ntrip) -> {RtkComponentType.CUSTOM}
                        getString(R.string.fc_setting_rtk_model_bluetooth) -> {RtkComponentType.BLUETOOTH}
                        getString(R.string.fc_setting_rtk_model_six_event) -> {RtkComponentType.SIXENTS}
                        else -> {RtkComponentType.NONE}
                    }
                    RtkManagerExt.getOriginManager()?.rtkComponentType = rtkType
                    updateRtkModuleType()
                }
                .show(parentFragmentManager)
        }
    }

    private fun updateRtkModuleType() {
        mBinding.llQxRtk.gone()
        mBinding.llCmccRtk.gone()
        mBinding.llSixentsRtk.gone()
        mBinding.llNtripRtk.gone()
        mBinding.llBluetoothRtk.gone()
         mBinding.tvRtkComponent.text = when (RtkManagerExt.getOriginManager()?.rtkComponentType) {
            RtkComponentType.QX -> {
                mBinding.llQxRtk.visible()
                setQxAccountParam((RtkManagerExt.getOriginManager()?.netWorkRtkManager as? QxRtkManager)?.account)
                getString(R.string.fc_setting_rtk_model_qx)
            }
            RtkComponentType.CMCC -> {
                mBinding.llCmccRtk.visible()
                setCmccAccountParam((RtkManagerExt.getOriginManager()?.netWorkRtkManager as? CmccRtkManager)?.account)
                getString(R.string.fc_setting_rtk_model_cmcc)
            }
            RtkComponentType.SIXENTS -> {
                mBinding.llSixentsRtk.visible()
                setSixentsAccountParam((RtkManagerExt.getOriginManager()?.netWorkRtkManager as? SixentsRtkManager)?.account)
                getString(R.string.fc_setting_rtk_model_six_event)
            }
            RtkComponentType.CUSTOM -> {
                mBinding.llNtripRtk.visible()
                setNtripAccountParam((RtkManagerExt.getOriginManager()?.netWorkRtkManager as? NtripClientRtkManager)?.account)
                getString(R.string.fc_setting_rtk_model_ntrip)
            }
            RtkComponentType.BLUETOOTH -> {
                mBinding.llBluetoothRtk.visible()
                getString(R.string.fc_setting_rtk_model_bluetooth)
            }
            RtkComponentType.NONE -> {
                getString(R.string.fc_setting_rtk_model_none)
            }
            else -> {""}
        }
    }

    private fun setNtripAccountParam(account: NtripClientAccount?) {
        account?.let {
            mBinding.ntripConfigRtkServer.param = account.ipAddress
            mBinding.ntripConfigRtkPort.param = account.port.toString()
            mBinding.ntripConfigRtkUsername.param = account.username
            mBinding.ntripConfigRtkPassword.param = account.password
            mBinding.ntripConfigRtkMount.param = account.mountPoint
        }
    }

    private fun setQxAccountParam(account: QxAccount?) {
        account?.let {
            mBinding.qxConfigRtkAccount.param = account.key
            mBinding.qxConfigRtkSecret.param = account.secret
            mBinding.qxConfigRtkId.param = account.deviceId
            mBinding.qxConfigRtkType.param = account.deviceType
        }
    }

    private fun setSixentsAccountParam(account: SixentsAccount?) {
        account?.let {
            mBinding.sixentsConfigRtkAccount.param = account.key
            mBinding.sixentsConfigRtkSecret.param = account.secret
            mBinding.sixentsConfigRtkId.param = account.deviceId
            mBinding.sixentsConfigRtkType.param = account.deviceType
        }
    }

    private fun setCmccAccountParam(account: CmccAccount?) {
        account?.let {
            mBinding.cmccConfigRtkId.param = account.deviceID
        }
    }

    private fun initRtkModuleEnable() {
        val isEnable = RtkManagerExt.getOriginManager()?.rtkEnable?:false
        mBinding.switchRtkEnable.isChecked = isEnable
        mBinding.switchRtkEnable.setOnCheckedChangeListener { compoundButton, b ->
            RtkManagerExt.setRtkEnableRx(b).subscribe()
        }
    }

    private fun getNtripErrorCodeMessage(code: Int): String {
        return when (code) {
            -10210 -> getString(R.string.fc_setting_rtk_connect_error_code_connected_failed)
            -10211 -> getString(R.string.fc_setting_rtk_connect_error_code_server_received_data_failed)
            -10212 -> getString(R.string.fc_setting_rtk_connect_error_code_server_unknown_exception)
            -10213 -> getString(R.string.fc_setting_rtk_connect_error_code_ntrip_auth_failed)
            -10214 -> getString(R.string.fc_setting_rtk_connect_error_code_unable_received_gga)
            -10215 -> getString(R.string.fc_setting_rtk_connect_error_code_unable_received_rtcm)
            0 -> getString(R.string.fc_setting_rtk_connect_error_code_not_connected)
            10200 -> getString(R.string.fc_setting_rtk_connect_error_code_connecting)
            10201 -> getString(R.string.fc_setting_rtk_connect_error_code_connected)
            else -> getString(R.string.unknown) + "$code"
        }
    }

    private fun getGpsPosTypeMessage(type: Int): String {
        return when (type) {
            0 -> getString(R.string.fc_setting_rtk_pos_state_no_gps)
            1 -> getString(R.string.fc_setting_rtk_pos_state_no_fix)
            2 -> getString(R.string.fc_setting_rtk_pos_state_2d_fix)
            3 -> getString(R.string.fc_setting_rtk_pos_state_3d_fix)
            4 -> getString(R.string.fc_setting_rtk_pos_state_gps)
            5 -> getString(R.string.fc_setting_rtk_pos_state_float)
            6 -> getString(R.string.fc_setting_rtk_pos_state_fixed)
            else -> getString(R.string.unknown) + "$type"
        }
    }
}